package ru.averta.notes.service.security;

import java.security.AccessControlException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;

import ru.averta.notes.domain.User;
import ru.averta.notes.domain.flags.IUserable;

import net.sourceforge.safr.core.invocation.MethodInvocation;
import net.sourceforge.safr.core.invocation.ProceedingInvocation;
import net.sourceforge.safr.core.provider.AccessManager;

public class AccessManagerImpl implements AccessManager {

    private final Logger logger = LoggerFactory.getLogger(AccessManagerImpl.class);

    @Autowired
    SecurityService security;

    public void checkCreate(Object arg0) {
        logger.trace("SAFR: checkCreate: {}", arg0);
        checkObjectAccess(arg0);
    }

    public void checkRead(Object arg0) {
        logger.trace("SAFR: checkRead: {}", arg0);
        checkObjectAccess(arg0);
    }

    public void checkUpdate(Object arg0) {
        logger.trace("SAFR: checkUpdate: {}", arg0);
        checkObjectAccess(arg0);
    }

    public void checkDelete(Object arg0) {
        logger.trace("SAFR: checkDelete: {}", arg0);
        checkObjectAccess(arg0);
    }

    private void checkObjectAccess(Object object) {
        User user = security.getCurrentUser();

        if (user == null) {
            logger.error("Не удалось получить доступ к объекту " + object + ", т.к. пользователь не залогинился");
            throw new AccessControlException("Не удалось получить текущего пользователя");
        }

        if (!(object instanceof IUserable)) {
            logger.error("Не удалось предоставить доступ к объекту " + object + ", т.к. объект не наследует IUserable");
            throw new AccessControlException("Доступ к объекту " + object + " не предоставлен");
        }

        IUserable userable = (IUserable) object;
        if ((userable.getUser() == null) || (!userable.getUser().equals(user))) {
            logger.debug("Пользователю " + user + " не предоставлен доступ к объекту " + object);
            throw new AccessControlException("Пользователю " + user + " не предоставлен доступ к объекту " + object);
        }
    }

    public Object checkCustomAfter(MethodInvocation arg0, Object arg1) {
        return null;
    }

    public Object checkCustomAround(ProceedingInvocation arg0) throws Throwable {
        return null;
    }

    public void checkCustomBefore(MethodInvocation arg0) {
        // Ничего делать не нужно
    }

    public void checkExecute(MethodInvocation arg0) {
        // Ничего делать не нужно
    }
}
